
#include "config.hpp"

#include "atr/core/float.hpp"

using namespace atr::core;

TEST(Core_FloatTest, Compile)
{
	_float<0,1>			f;		UNUSED(f);
	_double<0,2>		d;		UNUSED(d);

	_float<0,1,1>		f1;		UNUSED(f1);
	_double<0,2,1>		d1;		UNUSED(d1);

	_float<0,1,3>		f2;		UNUSED(f2);
	_double<0,2,3>		d2;		UNUSED(d2);

	_float<0,-1>		_f;		UNUSED(_f);
	_double<0,-2>		_d;		UNUSED(_d);

	_float<0,-1,1>		_f1;	UNUSED(_f1);
	_double<0,-2,1>		_d1;	UNUSED(_d1);

	_float<0,-1,3>		_f2;	UNUSED(_f2);
	_double<0,-2,3>		_d2;	UNUSED(_d2);
}

#define EXPECT_EQ_FLOAT(T, I, F)		\
	EXPECT_FLOAT_EQ ( I##.##F, static_cast< T >(_##T < I , F >()) )

TEST(Core_FloatTest, Float_DefaultBase)
{
	EXPECT_EQ_FLOAT ( float, 0, 0 );
	EXPECT_EQ_FLOAT ( float, 1, 0 );
	EXPECT_EQ_FLOAT ( float, 1, 1 );

	EXPECT_EQ_FLOAT ( float, 2, 0 );
	EXPECT_EQ_FLOAT ( float, 0, 2 );
	EXPECT_EQ_FLOAT ( float, 2, 2 );

	EXPECT_EQ_FLOAT ( float, 1, 10 );
	EXPECT_EQ_FLOAT ( float, 1, 100 );
	EXPECT_EQ_FLOAT ( float, 1, 1000 );

	EXPECT_EQ_FLOAT ( float, 1, 201 );
	EXPECT_EQ_FLOAT ( float, 123, 456 );
	EXPECT_EQ_FLOAT ( float, 321, 123 );

	EXPECT_EQ_FLOAT ( float, 2, 1 );
	EXPECT_EQ_FLOAT ( float, 5, 1 );
	EXPECT_EQ_FLOAT ( float, 123, 1 );
	EXPECT_EQ_FLOAT ( float, 154, 1 );
	EXPECT_EQ_FLOAT ( float, 2, 2 );
	EXPECT_EQ_FLOAT ( float, 5, 2 );
	EXPECT_EQ_FLOAT ( float, 123, 2 );
	EXPECT_EQ_FLOAT ( float, 154, 2 );

	EXPECT_EQ_FLOAT ( float, 1, 1 );
	EXPECT_EQ_FLOAT ( float, 1, 2 );
	EXPECT_EQ_FLOAT ( float, 1, 5 );

	EXPECT_EQ_FLOAT ( float, 2, 1 );
	EXPECT_EQ_FLOAT ( float, 5, 1 );

	EXPECT_EQ_FLOAT ( float, 2, 4 );
	EXPECT_EQ_FLOAT ( float, 4, 2 );
	EXPECT_EQ_FLOAT ( float, 6, 3 );
	EXPECT_EQ_FLOAT ( float, 3, 6 );

	EXPECT_EQ_FLOAT ( float, 20, 4 );
	EXPECT_EQ_FLOAT ( float, 100, 4 );
	EXPECT_EQ_FLOAT ( float, 4, 20 );
	EXPECT_EQ_FLOAT ( float, 4, 40 );
	EXPECT_EQ_FLOAT ( float, 4, 41 );
	EXPECT_EQ_FLOAT ( float, 4, 50 );
	EXPECT_EQ_FLOAT ( float, 4, 100 );
}

TEST(Core_FloatTest, Double_DefaultBase)
{
	EXPECT_EQ_FLOAT ( double, 0, 0 );
	EXPECT_EQ_FLOAT ( double, 1, 0 );
	EXPECT_EQ_FLOAT ( double, 1, 1 );

	EXPECT_EQ_FLOAT ( double, 2, 0 );
	EXPECT_EQ_FLOAT ( double, 0, 2 );
	EXPECT_EQ_FLOAT ( double, 2, 2 );

	EXPECT_EQ_FLOAT ( double, 1, 10 );
	EXPECT_EQ_FLOAT ( double, 1, 100 );
	EXPECT_EQ_FLOAT ( double, 1, 1000 );

	EXPECT_EQ_FLOAT ( double, 1, 201 );
	EXPECT_EQ_FLOAT ( double, 123, 456 );
	EXPECT_EQ_FLOAT ( double, 321, 123 );

	EXPECT_EQ_FLOAT ( double, 2, 1 );
	EXPECT_EQ_FLOAT ( double, 5, 1 );
	EXPECT_EQ_FLOAT ( double, 123, 1 );
	EXPECT_EQ_FLOAT ( double, 154, 1 );
	EXPECT_EQ_FLOAT ( double, 2, 2 );
	EXPECT_EQ_FLOAT ( double, 5, 2 );
	EXPECT_EQ_FLOAT ( double, 123, 2 );
	EXPECT_EQ_FLOAT ( double, 154, 2 );

	EXPECT_EQ_FLOAT ( double, 1, 1 );
	EXPECT_EQ_FLOAT ( double, 1, 2 );
	EXPECT_EQ_FLOAT ( double, 1, 5 );

	EXPECT_EQ_FLOAT ( double, 2, 1 );
	EXPECT_EQ_FLOAT ( double, 5, 1 );

	EXPECT_EQ_FLOAT ( double, 2, 4 );
	EXPECT_EQ_FLOAT ( double, 4, 2 );
	EXPECT_EQ_FLOAT ( double, 6, 3 );
	EXPECT_EQ_FLOAT ( double, 3, 6 );

	EXPECT_EQ_FLOAT ( double, 20, 4 );
	EXPECT_EQ_FLOAT ( double, 100, 4 );
	EXPECT_EQ_FLOAT ( double, 4, 20 );
	EXPECT_EQ_FLOAT ( double, 4, 40 );
	EXPECT_EQ_FLOAT ( double, 4, 41 );
	EXPECT_EQ_FLOAT ( double, 4, 50 );
	EXPECT_EQ_FLOAT ( double, 4, 100 );
}

TEST(Core_FloatTest, Float_DefaultBase_Negative)
{
	EXPECT_EQ_FLOAT ( float, -0, 0 );
	EXPECT_EQ_FLOAT ( float, -1, 0 );
	EXPECT_EQ_FLOAT ( float, -1, 1 );

	EXPECT_EQ_FLOAT ( float, -2, 0 );
	//EXPECT_EQ_FLOAT ( float, -0, 2 );	
	EXPECT_FLOAT_EQ ( -0.2, static_cast<float>(_float<0, -2>()) ); // FIXME
	EXPECT_EQ_FLOAT ( float, -2, 2 );

	EXPECT_EQ_FLOAT ( float, -1, 10 );
	EXPECT_EQ_FLOAT ( float, -1, 100 );
	EXPECT_EQ_FLOAT ( float, -1, 1000 );

	EXPECT_EQ_FLOAT ( float, -1, 201 );
	EXPECT_EQ_FLOAT ( float, -123, 456 );
	EXPECT_EQ_FLOAT ( float, -321, 123 );

	EXPECT_EQ_FLOAT ( float, -2, 1 );
	EXPECT_EQ_FLOAT ( float, -5, 1 );
	EXPECT_EQ_FLOAT ( float, -123, 1 );
	EXPECT_EQ_FLOAT ( float, -154, 1 );
	EXPECT_EQ_FLOAT ( float, -2, 2 );
	EXPECT_EQ_FLOAT ( float, -5, 2 );
	EXPECT_EQ_FLOAT ( float, -123, 2 );
	EXPECT_EQ_FLOAT ( float, -154, 2 );

	EXPECT_EQ_FLOAT ( float, -1, 1 );
	EXPECT_EQ_FLOAT ( float, -1, 2 );
	EXPECT_EQ_FLOAT ( float, -1, 5 );

	EXPECT_EQ_FLOAT ( float, -2, 1 );
	EXPECT_EQ_FLOAT ( float, -5, 1 );

	EXPECT_EQ_FLOAT ( float, -2, 4 );
	EXPECT_EQ_FLOAT ( float, -4, 2 );
	EXPECT_EQ_FLOAT ( float, -6, 3 );
	EXPECT_EQ_FLOAT ( float, -3, 6 );

	EXPECT_EQ_FLOAT ( float, -20, 4 );
	EXPECT_EQ_FLOAT ( float, -100, 4 );
	EXPECT_EQ_FLOAT ( float, -4, 20 );
	EXPECT_EQ_FLOAT ( float, -4, 40 );
	EXPECT_EQ_FLOAT ( float, -4, 41 );
	EXPECT_EQ_FLOAT ( float, -4, 50 );
	EXPECT_EQ_FLOAT ( float, -4, 100 );
}

TEST(Core_FloatTest, Double_DefaultBase_Negative)
{
	EXPECT_EQ_FLOAT ( double, -0, 0 );
	EXPECT_EQ_FLOAT ( double, -1, 0 );
	EXPECT_EQ_FLOAT ( double, -1, 1 );

	EXPECT_EQ_FLOAT ( double, -2, 0 );
	//EXPECT_EQ_FLOAT ( double, -0, 2 );	
	EXPECT_FLOAT_EQ ( -0.2, static_cast<double>(_double<0, -2>()) ); // FIXME
	EXPECT_EQ_FLOAT ( double, -2, 2 );

	EXPECT_EQ_FLOAT ( double, -1, 10 );
	EXPECT_EQ_FLOAT ( double, -1, 100 );
	EXPECT_EQ_FLOAT ( double, -1, 1000 );

	EXPECT_EQ_FLOAT ( double, -1, 201 );
	EXPECT_EQ_FLOAT ( double, -123, 456 );
	EXPECT_EQ_FLOAT ( double, -321, 123 );

	EXPECT_EQ_FLOAT ( double, -2, 1 );
	EXPECT_EQ_FLOAT ( double, -5, 1 );
	EXPECT_EQ_FLOAT ( double, -123, 1 );
	EXPECT_EQ_FLOAT ( double, -154, 1 );
	EXPECT_EQ_FLOAT ( double, -2, 2 );
	EXPECT_EQ_FLOAT ( double, -5, 2 );
	EXPECT_EQ_FLOAT ( double, -123, 2 );
	EXPECT_EQ_FLOAT ( double, -154, 2 );

	EXPECT_EQ_FLOAT ( double, -1, 1 );
	EXPECT_EQ_FLOAT ( double, -1, 2 );
	EXPECT_EQ_FLOAT ( double, -1, 5 );

	EXPECT_EQ_FLOAT ( double, -5, 1 );
	EXPECT_EQ_FLOAT ( double, -2, 1 );

	EXPECT_EQ_FLOAT ( double, -2, 4 );
	EXPECT_EQ_FLOAT ( double, -4, 2 );
	EXPECT_EQ_FLOAT ( double, -6, 3 );
	EXPECT_EQ_FLOAT ( double, -3, 6 );

	EXPECT_EQ_FLOAT ( double, -20, 4 );
	EXPECT_EQ_FLOAT ( double, -100, 4 );
	EXPECT_EQ_FLOAT ( double, -4, 20 );
	EXPECT_EQ_FLOAT ( double, -4, 40 );
	EXPECT_EQ_FLOAT ( double, -4, 41 );
	EXPECT_EQ_FLOAT ( double, -4, 50 );
	EXPECT_EQ_FLOAT ( double, -4, 100 );
}

#undef EXPECT_EQ_FLOAT

#define EXPECT_EQ_FLOAT(T, I, F, B)		\
	EXPECT_FLOAT_EQ ( I##.##B##F, static_cast< T >(_##T < I , F , 1##B >()) )

TEST(Core_FloatTest, Float_Base)
{
	EXPECT_EQ_FLOAT ( float, 0, 0, 000 );
	EXPECT_EQ_FLOAT ( float, 1, 0, 000 );
	EXPECT_EQ_FLOAT ( float, 1, 1, 000 );

	EXPECT_EQ_FLOAT ( float, 2, 0, 0 );
	EXPECT_EQ_FLOAT ( float, 0, 2, 0  );
	EXPECT_EQ_FLOAT ( float, 2, 2, 0 );

	EXPECT_EQ_FLOAT ( float, 1, 10,   00 );
	EXPECT_EQ_FLOAT ( float, 1, 100,  00 );
	EXPECT_EQ_FLOAT ( float, 1, 1000, 00 );

	EXPECT_EQ_FLOAT ( float, 1,   201, 0 );
	EXPECT_EQ_FLOAT ( float, 123, 456, 00 );
	EXPECT_EQ_FLOAT ( float, 321, 123, 000 );

	EXPECT_EQ_FLOAT ( float, 2,   1, 0 );
	EXPECT_EQ_FLOAT ( float, 5,   1, 00 );
	EXPECT_EQ_FLOAT ( float, 123, 1, 000 );
	EXPECT_EQ_FLOAT ( float, 154, 1, 0000 );
	EXPECT_EQ_FLOAT ( float, 2,   2, 00000 );
	EXPECT_EQ_FLOAT ( float, 5,   2, 000000 );
	EXPECT_EQ_FLOAT ( float, 123, 2, 000000 );
	EXPECT_EQ_FLOAT ( float, 154, 2, 0000000 );

	EXPECT_EQ_FLOAT ( float, 1, 1, 00 );
	EXPECT_EQ_FLOAT ( float, 1, 2, 000 );
	EXPECT_EQ_FLOAT ( float, 1, 5, 0000 );

	EXPECT_EQ_FLOAT ( float, 2, 1, 00000 );
	EXPECT_EQ_FLOAT ( float, 5, 1, 000000 );

	EXPECT_EQ_FLOAT ( float, 2, 4, 0000000 );
	EXPECT_EQ_FLOAT ( float, 4, 2, 00000000 );
	EXPECT_EQ_FLOAT ( float, 6, 3, 000000000 );
	EXPECT_EQ_FLOAT ( float, 3, 6, 000000000 );

	EXPECT_EQ_FLOAT ( float, 20,  4,   0 );
	EXPECT_EQ_FLOAT ( float, 100, 4,   00 );
	EXPECT_EQ_FLOAT ( float, 4,   20,  000 );
	EXPECT_EQ_FLOAT ( float, 4,   40,  0000 );
	EXPECT_EQ_FLOAT ( float, 4,   41,  00000 );
	EXPECT_EQ_FLOAT ( float, 4,   50,  000000 );
	EXPECT_EQ_FLOAT ( float, 4,   100, 000000 );
}

TEST(Core_FloatTest, Double_Base)
{
	EXPECT_EQ_FLOAT ( double, 1, 1, 000 );
	EXPECT_EQ_FLOAT ( double, 0, 0, 000 );
	EXPECT_EQ_FLOAT ( double, 1, 0, 000 );

	EXPECT_EQ_FLOAT ( double, 2, 0, 0 );
	EXPECT_EQ_FLOAT ( double, 0, 2, 0  );
	EXPECT_EQ_FLOAT ( double, 2, 2, 0 );

	EXPECT_EQ_FLOAT ( double, 1, 10,   00 );
	EXPECT_EQ_FLOAT ( double, 1, 100,  00 );
	EXPECT_EQ_FLOAT ( double, 1, 1000, 00 );

	EXPECT_EQ_FLOAT ( double, 1,   201, 0 );
	EXPECT_EQ_FLOAT ( double, 123, 456, 00 );
	EXPECT_EQ_FLOAT ( double, 321, 123, 000 );

	EXPECT_EQ_FLOAT ( double, 2,   1, 0 );
	EXPECT_EQ_FLOAT ( double, 5,   1, 00 );
	EXPECT_EQ_FLOAT ( double, 123, 1, 000 );
	EXPECT_EQ_FLOAT ( double, 154, 1, 0000 );
	EXPECT_EQ_FLOAT ( double, 2,   2, 00000 );
	EXPECT_EQ_FLOAT ( double, 5,   2, 000000 );
	EXPECT_EQ_FLOAT ( double, 123, 2, 000000 );
	EXPECT_EQ_FLOAT ( double, 154, 2, 0000000 );

	EXPECT_EQ_FLOAT ( double, 1, 1, 00 );
	EXPECT_EQ_FLOAT ( double, 1, 2, 000 );
	EXPECT_EQ_FLOAT ( double, 1, 5, 0000 );

	EXPECT_EQ_FLOAT ( double, 5, 1, 000000 );
	EXPECT_EQ_FLOAT ( double, 2, 1, 00000 );

	EXPECT_EQ_FLOAT ( double, 2, 4, 0000000 );
	EXPECT_EQ_FLOAT ( double, 4, 2, 00000000 );
	EXPECT_EQ_FLOAT ( double, 6, 3, 000000000 );
	EXPECT_EQ_FLOAT ( double, 3, 6, 000000000 );

	EXPECT_EQ_FLOAT ( double, 20,  4,   0 );
	EXPECT_EQ_FLOAT ( double, 100, 4,   00 );
	EXPECT_EQ_FLOAT ( double, 4,   20,  000 );
	EXPECT_EQ_FLOAT ( double, 4,   40,  0000 );
	EXPECT_EQ_FLOAT ( double, 4,   41,  00000 );
	EXPECT_EQ_FLOAT ( double, 4,   50,  000000 );
	EXPECT_EQ_FLOAT ( double, 4,   100, 000000 ); 
}


TEST(Core_FloatTest, Float_Base_Negative)
{
	EXPECT_EQ_FLOAT ( float, -0, 0, 000 );
	EXPECT_EQ_FLOAT ( float, -1, 0, 000 );
	EXPECT_EQ_FLOAT ( float, -1, 1, 000 );

	EXPECT_EQ_FLOAT ( float, -2, 0, 0 );
	//EXPECT_EQ_FLOAT ( float, -0, 2 );	
	EXPECT_FLOAT_EQ ( -0.2, static_cast<float>(_float<0, -2>()) ); // FIXME
	EXPECT_EQ_FLOAT ( float, -2, 2, 0 );

	EXPECT_EQ_FLOAT ( float, -1, 10,   00 );
	EXPECT_EQ_FLOAT ( float, -1, 100,  00 );
	EXPECT_EQ_FLOAT ( float, -1, 1000, 00 );

	EXPECT_EQ_FLOAT ( float, -1,   201, 0 );
	EXPECT_EQ_FLOAT ( float, -123, 456, 00 );
	EXPECT_EQ_FLOAT ( float, -321, 123, 000 );

	EXPECT_EQ_FLOAT ( float, -2,   1, 0 );
	EXPECT_EQ_FLOAT ( float, -5,   1, 00 );
	EXPECT_EQ_FLOAT ( float, -123, 1, 000 );
	EXPECT_EQ_FLOAT ( float, -154, 1, 0000 );
	EXPECT_EQ_FLOAT ( float, -2,   2, 00000 );
	EXPECT_EQ_FLOAT ( float, -5,   2, 000000 );
	EXPECT_EQ_FLOAT ( float, -123, 2, 000000 );
	EXPECT_EQ_FLOAT ( float, -154, 2, 0000000 );

	EXPECT_EQ_FLOAT ( float, -1, 1, 00 );
	EXPECT_EQ_FLOAT ( float, -1, 2, 000 );
	EXPECT_EQ_FLOAT ( float, -1, 5, 0000 );

	EXPECT_EQ_FLOAT ( float, -2, 1, 00000 );
	EXPECT_EQ_FLOAT ( float, -5, 1, 000000 );

	EXPECT_EQ_FLOAT ( float, -2, 4, 0000000 );
	EXPECT_EQ_FLOAT ( float, -4, 2, 00000000 );
	EXPECT_EQ_FLOAT ( float, -6, 3, 000000000 );
	EXPECT_EQ_FLOAT ( float, -3, 6, 000000000 );

	EXPECT_EQ_FLOAT ( float, -20,  4,   0 );
	EXPECT_EQ_FLOAT ( float, -100, 4,   00 );
	EXPECT_EQ_FLOAT ( float, -4,   20,  000 );
	EXPECT_EQ_FLOAT ( float, -4,   40,  0000 );
	EXPECT_EQ_FLOAT ( float, -4,   41,  00000 );
	EXPECT_EQ_FLOAT ( float, -4,   50,  000000 );
	EXPECT_EQ_FLOAT ( float, -4,   100, 000000 ); 
}

TEST(Core_FloatTest, Double_Base_Negative)
{
	EXPECT_EQ_FLOAT ( double, -0, 0, 000 );
	EXPECT_EQ_FLOAT ( double, -1, 0, 000 );
	EXPECT_EQ_FLOAT ( double, -1, 1, 000 );

	//EXPECT_EQ_FLOAT ( double, -0, 2 );	
	EXPECT_FLOAT_EQ ( -0.2, static_cast<double>(_float<0, -2>()) ); // FIXME
	EXPECT_EQ_FLOAT ( double, -2, 2, 0 );

	EXPECT_EQ_FLOAT ( double, -1, 10,   00 );
	EXPECT_EQ_FLOAT ( double, -1, 100,  00 );
	EXPECT_EQ_FLOAT ( double, -1, 1000, 00 );

	EXPECT_EQ_FLOAT ( double, -1,   201, 0 );
	EXPECT_EQ_FLOAT ( double, -123, 456, 00 );
	EXPECT_EQ_FLOAT ( double, -321, 123, 000 );

	EXPECT_EQ_FLOAT ( double, -2,   1, 0 );
	EXPECT_EQ_FLOAT ( double, -5,   1, 00 );
	EXPECT_EQ_FLOAT ( double, -123, 1, 000 );
	EXPECT_EQ_FLOAT ( double, -154, 1, 0000 );
	EXPECT_EQ_FLOAT ( double, -2,   2, 00000 );
	EXPECT_EQ_FLOAT ( double, -5,   2, 000000 );
	EXPECT_EQ_FLOAT ( double, -123, 2, 000000 );
	EXPECT_EQ_FLOAT ( double, -154, 2, 0000000 );

	EXPECT_EQ_FLOAT ( double, -1, 1, 00 );
	EXPECT_EQ_FLOAT ( double, -1, 2, 000 );
	EXPECT_EQ_FLOAT ( double, -1, 5, 0000 );

	EXPECT_EQ_FLOAT ( double, -2, 1, 00000 );
	EXPECT_EQ_FLOAT ( double, -5, 1, 000000 );

	EXPECT_EQ_FLOAT ( double, -2, 4, 0000000 );
	EXPECT_EQ_FLOAT ( double, -4, 2, 00000000 );
	EXPECT_EQ_FLOAT ( double, -6, 3, 000000000 );
	EXPECT_EQ_FLOAT ( double, -3, 6, 000000000 );

	EXPECT_EQ_FLOAT ( double, -20,  4,   0 );
	EXPECT_EQ_FLOAT ( double, -100, 4,   00 );
	EXPECT_EQ_FLOAT ( double, -4,   20,  000 );
	EXPECT_EQ_FLOAT ( double, -4,   40,  0000 );
	EXPECT_EQ_FLOAT ( double, -4,   41,  00000 );
	EXPECT_EQ_FLOAT ( double, -4,   50,  000000 );
	EXPECT_EQ_FLOAT ( double, -4,   100, 000000 ); 
}

#undef EXPECT_EQ_FLOAT
